﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NopSolutions.NopCommerce.BusinessLogic.Payment;
using NopSolutions.NopCommerce.Common;
using NopSolutions.NopCommerce.BusinessLogic.Orders;
using NopSolutions.NopCommerce.BusinessLogic.CustomerManagement;
using System.Globalization;
using NopSolutions.NopCommerce.Common.Utils;
using System.Text;
using NopSolutions.NopCommerce.BusinessLogic.Directory;
using System.Security.Cryptography;

namespace MediaCoders.NopCommerce.Code.MultiSafePay
{
    /// <summary>
    /// NopCommerce payment processor for MultiSafePay
    /// </summary>
    public class MultiSafePayPaymentProcessor : IPaymentMethod
    {
        #region Public Methods
        /// <summary>
        /// Process payment
        /// </summary>
        /// <param name="paymentInfo">Payment info required for an order processing</param>
        /// <param name="customer">Customer</param>
        /// <param name="orderGuid">Unique order identifier</param>
        /// <param name="processPaymentResult">Process payment result</param>
        public void ProcessPayment(PaymentInfo paymentInfo, Customer customer, Guid orderGuid, ref ProcessPaymentResult processPaymentResult)
        {
            processPaymentResult.PaymentStatus = PaymentStatusEnum.Pending;
        }

        /// <summary>
        /// Post process payment (payment gateways that require redirecting)
        /// </summary>
        /// <param name="order">Order</param>
        /// <returns>The error status, or String.Empty if no errors</returns>
        public string PostProcessPayment(Order order)
        {
            MultiSafePay msp = new MultiSafePay(order);

            msp.Customer.Firstname = order.Customer.FirstName;
            msp.Customer.Lastname = order.Customer.LastName;
            msp.Customer.Address1 = order.Customer.BillingAddresses[order.Customer.BillingAddressId].Address1;
            msp.Customer.Address2 = order.Customer.BillingAddresses[order.Customer.BillingAddressId].Address2;
            msp.Customer.Zipcode = order.Customer.BillingAddresses[order.Customer.BillingAddressId].ZipPostalCode;
            msp.Customer.State = order.Customer.BillingAddresses[order.Customer.BillingAddressId].StateProvince.Name;
            msp.Customer.City = order.Customer.BillingAddresses[order.Customer.BillingAddressId].City;
            msp.Customer.Country = order.Customer.BillingAddresses[order.Customer.BillingAddressId].Country.Name;
            msp.Customer.Email = order.Customer.BillingAddresses[order.Customer.BillingAddressId].Email;
            msp.Customer.Phone = order.Customer.BillingAddresses[order.Customer.BillingAddressId].PhoneNumber;

            msp.Transaction.Currency = "EUR";
            msp.Transaction.ID = order.OrderId.ToString();
            msp.Transaction.Amount = ((int)(order.OrderTotal * 100)).ToString();
            msp.Transaction.Description = "Betaling voor order " + order.OrderId.ToString();
            msp.Transaction.Items = GetItems(order);

            string paymentUrl = msp.StartTransaction();
            string returnvalue = string.Empty;

            if (!string.IsNullOrEmpty(paymentUrl))
            {
                HttpContext.Current.Response.Redirect(paymentUrl);
            }
            else
            {
                returnvalue = msp.ErrorDescription;
            }

            return returnvalue;
        }

        /// <summary>
        /// Gets additional handling fee
        /// </summary>
        /// <returns>Additional handling fee</returns>
        public decimal GetAdditionalHandlingFee()
        {
            return MultiSafePayPaymentSettings.AdditionalFee;
        }

        /// <summary>
        /// Captures payment
        /// </summary>
        /// <param name="order">Order</param>
        /// <param name="processPaymentResult">Process payment result</param>
        public void Capture(Order order, ref ProcessPaymentResult processPaymentResult)
        {
            throw new NopException("Capture method not supported");
        }

        /// <summary>
        /// Refunds payment
        /// </summary>
        /// <param name="order">Order</param>
        /// <param name="cancelPaymentResult">Cancel payment result</param>        
        public void Refund(Order order, ref CancelPaymentResult cancelPaymentResult)
        {
            throw new NopException("Refund method not supported");
        }

        /// <summary>
        /// Voids payment
        /// </summary>
        /// <param name="order">Order</param>
        /// <param name="cancelPaymentResult">Cancel payment result</param>        
        public void Void(Order order, ref CancelPaymentResult cancelPaymentResult)
        {
            throw new NopException("Void method not supported");
        }

        /// <summary>
        /// Process recurring payment
        /// </summary>
        /// <param name="paymentInfo">Payment info required for an order processing</param>
        /// <param name="customer">Customer</param>
        /// <param name="orderGuid">Unique order identifier</param>
        /// <param name="processPaymentResult">Process payment result</param>
        public void ProcessRecurringPayment(PaymentInfo paymentInfo, Customer customer, Guid orderGuid, ref ProcessPaymentResult processPaymentResult)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Cancels recurring payment
        /// </summary>
        /// <param name="order">Order</param>
        /// <param name="cancelPaymentResult">Cancel payment result</param>        
        public void CancelRecurringPayment(Order order, ref CancelPaymentResult cancelPaymentResult)
        {
            throw new NotImplementedException();
        }
        #endregion

        #region Private Methods

        private string GetItems(Order order)
        {
            StringBuilder items = new StringBuilder();

            items.Append("<ul>");

            foreach (var item in order.OrderProductVariants)
            {
                items.AppendFormat("<li>{0} ({1}x)</li>", item.ProductVariant.FullProductName, item.Quantity);
            }

            items.Append("</ul>");

            return items.ToString();
        }

        #endregion

        #region Properies

        /// <summary>
        /// Gets a value indicating whether capture is supported
        /// </summary>
        public bool CanCapture
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// Gets a value indicating whether refund is supported
        /// </summary>
        public bool CanRefund
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// Gets a value indicating whether void is supported
        /// </summary>
        public bool CanVoid
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// Gets a recurring payment type of payment method
        /// </summary>
        /// <returns>A recurring payment type of payment method</returns>
        public RecurringPaymentTypeEnum SupportRecurringPayments
        {
            get
            {
                return RecurringPaymentTypeEnum.NotSupported;
            }
        }

        /// <summary>
        /// Gets a payment method type
        /// </summary>
        /// <returns>A payment method type</returns>
        public PaymentMethodTypeEnum PaymentMethodType
        {
            get
            {
                return PaymentMethodTypeEnum.Standard;
            }
        }
        #endregion
    }
}